#include <utitl/thread.h>
#include <utitl/logger.h>

namespace ECG{
namespace Utitl{

    thread::thread()
    :m_detachable(true)
    ,m_stackSize(0)
    ,m_tid(0)
    {
        m_ret = NULL;
    }

    thread::~thread()
    {

    }

   bool thread::start()
   {
       pthread_attr_t attr;
       pthread_attr_init(&attr);
       if(m_detachable)
       {
           pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
       }
       if(m_stackSize > 0)
       {
            pthread_attr_setstacksize(&attr,m_stackSize);
       }
       int ret = pthread_create(&m_tid,&attr,threadFunc,this);
       if(ret != 0)
       {
           log_error() << "failed to create pthread,return = " << ret;
           return false;
       }
       
       return true;
   }

   bool thread::stop()
   {
       int ret;
       ret = pthread_cancel(m_tid);
       if(ret<0){
           return false;
       }
       if(!m_detachable){
            ret = pthread_join(m_tid,&m_ret);
            if(ret < 0){
                return false;
            }
       }
       return true;
   }

   bool thread::wait(void **out)
   {
       int ret;
       if(m_detachable)
       {
           return false;
       }
       ret = pthread_join(m_tid,&m_ret);
       if(ret<0){
           return false;
       }
       out = &m_ret;
       return true;
   }

   thread& thread::setDetachable(bool yes)
   {
       m_detachable = yes;
       return *this;
   }

   thread& thread::setStackSize(size_t size)
   {
       m_stackSize = size;
       return *this;
   }

   unsigned long thread::getID() const
   {
       return m_tid;
   }

   void* thread::threadFunc(void* arg)
   {
       thread* thr = (thread*)arg;
       if(thr->m_detachable){
           return thr->run();
       }
       thr->m_ret = thr->run();
       return thr->m_ret;
   }

}
}

